From 74ca29440e46136504ed6fc811ccd60da8af8abc Mon Sep 17 00:00:00 2001
From: David Bremner <david@tethera.net>
Date: Wed, 26 Oct 2016 22:18:48 -0300
Subject: [PATCH 1/3] debcherry fixup patch

88800f7 J2K: use g_strlcpy() instead of g_snprintf()
	 - no changes against upstream or conflicts
c6e0b7c FindOpenJPEG.cmake: use HINTS, not PATHS. NO_DEFAULT_PATH is not needed.
	 - no changes against upstream or conflicts
5cf698f Port to OpenJPEG2
	 - extra changes or conflicts
6f48d69 FindOpenJPEG.cmake: pick right include path if multiple headers.
	 - extra changes or conflicts
acf974a Update cmake stuff to look for OpenJPEG2 (openjpeg >= 2.0.0 aka openjp2)
	 - extra changes or conflicts
ecef362 restore upstream TODO
	 - no changes against upstream or conflicts
898199a debian: cleanup useless / missing docs
	 - extra changes or conflicts
31da456 remove dcraw.c again
	 - no changes against upstream or conflicts
4c3f916 remove dcraw.c
	 - no changes against upstream or conflicts
3b395b6 "undelete" some files now shipped in upstream tarball
	 - extra changes or conflicts
7d30472 remove version.h from git;  generate it at build time
	 - no changes against upstream or conflicts
7441226 remove version.sh, unneeded for build
	 - no changes against upstream or conflicts
b0be4a0 commit version.h, version.sh for new version
	 - extra changes or conflicts
b5784e1 commit version.sh for current upstream snapshot
	 - extra changes or conflicts
cea1f68 remove generated files that are no longer carried in upstream branch (since we are not going to import them from tarballs.
	 - extra changes or conflicts
f67ef8e Revert "As a workaround, add files to POTFILES.skip"
	 - extra changes or conflicts
f6a4d09 As a workaround, add files to POTFILES.skip
	 - extra changes or conflicts
1eb15b3 Imported Upstream version 0.5
	 - extra changes or conflicts
---
 cmake/modules/FindOpenJPEG.cmake  | 112 ++++---------------
 src/CMakeLists.txt                |  17 +--
 src/common/imageio_j2k.c          | 228 ++++++++++++++++++++++----------------
 src/imageio/format/CMakeLists.txt |   4 +-
 src/imageio/format/j2k.c          | 130 +++++++++++-----------
 5 files changed, 224 insertions(+), 267 deletions(-)

diff --git a/cmake/modules/FindOpenJPEG.cmake b/cmake/modules/FindOpenJPEG.cmake
index b80f922..da6d275 100644
--- a/cmake/modules/FindOpenJPEG.cmake
+++ b/cmake/modules/FindOpenJPEG.cmake
@@ -1,101 +1,29 @@
-# - Find OpenJPEG library
-# Find the native OpenJPEG includes and library
-# This module defines
-#  OPENJPEG_INCLUDE_DIRS, where to find openjpeg.h, Set when
-#                        OPENJPEG_INCLUDE_DIR is found.
-#  OPENJPEG_LIBRARIES, libraries to link against to use OpenJPEG.
-#  OPENJPEG_ROOT_DIR, The base directory to search for OpenJPEG.
-#                    This can also be an environment variable.
-#  OPENJPEG_FOUND, If false, do not try to use OpenJPEG.
+# - Try to find OpenJPEG
+# Once done, this will define
 #
-# also defined, but not for general use are
-#  OPENJPEG_LIBRARY, where to find the OpenJPEG library.
-
-#=============================================================================
-# Copyright 2011 Blender Foundation.
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-
-# If OPENJPEG_ROOT_DIR was defined in the environment, use it.
-IF(NOT OPENJPEG_ROOT_DIR AND NOT $ENV{OPENJPEG_ROOT_DIR} STREQUAL "")
-  SET(OPENJPEG_ROOT_DIR $ENV{OPENJPEG_ROOT_DIR})
-ENDIF()
+#  OpenJPEG_FOUND - system has OpenJPEG
+#  OpenJPEG_INCLUDE_DIRS - the OpenJPEG include directories
+#  OpenJPEG_LIBRARIES - link these to use OpenJPEG
 
 include(LibFindMacros)
 
-libfind_pkg_check_modules(PC_OPENJPEG libopenjpeg1)
+# Use pkg-config to get hints about paths
+libfind_pkg_check_modules(OpenJPEG_PKGCONF libopenjp2)
 
-SET(_openjpeg_SEARCH_DIRS
-  ${OPENJPEG_ROOT_DIR}
-  /usr/local
-  /sw # Fink
-  /opt/local # DarwinPorts
-  /opt/csw # Blastwave
+# Include dir
+find_path(OpenJPEG_INCLUDE_DIR
+  NAMES openjpeg.h
+  HINTS ${OpenJPEG_PKGCONF_INCLUDE_DIRS}
 )
 
-FIND_PATH(OPENJPEG_INCLUDE_DIR
-  NAMES
-    openjpeg.h
-  HINTS
-    ${PC_OPENJPEG_INCLUDEDIR}
-    ${PC_OPENJPEG_INCLUDE_DIRS}
-    ${_openjpeg_SEARCH_DIRS}
-  PATH_SUFFIXES
-    include
+# Finally the library itself
+find_library(OpenJPEG_LIBRARY
+  NAMES openjp2
+  HINTS ${OpenJPEG_PKGCONF_LIBRARY_DIRS}
 )
 
-FIND_LIBRARY(OPENJPEG_LIBRARY
-  NAMES
-    openjpeg
-  HINTS
-    ${PC_OPENJPEG_LIBDIR}
-    ${PC_OPENJPEG_LIBRARY_DIRS}
-    ${_openjpeg_SEARCH_DIRS}
-  PATH_SUFFIXES
-    lib64 lib
-  )
-
-# handle the QUIETLY and REQUIRED arguments and set OPENJPEG_FOUND to TRUE if
-# all listed variables are TRUE
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenJPEG DEFAULT_MSG
-    OPENJPEG_LIBRARY OPENJPEG_INCLUDE_DIR)
-
-IF(OPENJPEG_FOUND)
-  SET(OPENJPEG_LIBRARIES ${OPENJPEG_LIBRARY})
-  SET(OPENJPEG_INCLUDE_DIRS ${OPENJPEG_INCLUDE_DIR})
-
-  # 1.3 didn't have pkg-config support, so we can't use that to get the version.
-  # 1.5 no longer has the #define OPENJPEG_VERSION ... in openjpeg.h so we can't use that either.
-  # Thus we might have to compile a smalltest program to get the version string. Could someone please kill me?
-
-  # see if pkg-config found the library. this should succeed for cross compiles as they are harder to run test programs
-  if(NOT "${PC_OPENJPEG_VERSION}" STREQUAL "")
-    # use the version as found by pkg-config
-    set(OPENJPEG_VERSION ${PC_OPENJPEG_VERSION})
-  else(NOT "${PC_OPENJPEG_VERSION}" STREQUAL "")
-    # too bad, we have to run our test code
-    try_run(run_var result_var
-            ${CMAKE_BINARY_DIR}/CMakeTmp
-            ${CMAKE_SOURCE_DIR}/cmake/modules/openjpeg_version.c
-            CMAKE_FLAGS "-DLINK_LIBRARIES:STRING=${OPENJPEG_LIBRARIES}"
-                        "-DINCLUDE_DIRECTORIES:STRING=${OPENJPEG_INCLUDE_DIRS}"
-            RUN_OUTPUT_VARIABLE rout_var
-    )
-    if(result_var)
-      set(OPENJPEG_VERSION ${rout_var})
-    endif(result_var)
-  endif(NOT "${PC_OPENJPEG_VERSION}" STREQUAL "")
-
-ENDIF(OPENJPEG_FOUND)
-
-MARK_AS_ADVANCED(
-  OPENJPEG_INCLUDE_DIR
-  OPENJPEG_LIBRARY
-)
+# Set the include dir variables and the libraries and let libfind_process do the rest.
+# NOTE: Singular variables for this library, plural for libraries this this lib depends on.
+set(OpenJPEG_PROCESS_INCLUDES OpenJPEG_INCLUDE_DIR)
+set(OpenJPEG_PROCESS_LIBS OpenJPEG_LIBRARY)
+libfind_process(OpenJPEG)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9278d91..7d29528 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -225,18 +225,13 @@ endif(USE_FLICKR)
 
 if(USE_OPENJPEG)
   find_package(OpenJPEG)
-  if(OPENJPEG_FOUND)
-    list(APPEND SOURCES "common/imageio_j2k.c")
-    include_directories(SYSTEM ${OPENJPEG_INCLUDE_DIRS})
-    list(APPEND LIBS ${OPENJPEG_LIBRARIES})
-    add_definitions(${OPENJPEG_DEFINITIONS})
+  if(OpenJPEG_FOUND)
     add_definitions("-DHAVE_OPENJPEG")
-    if(OPENJPEG_VERSION VERSION_LESS "1.5.0")
-      message(STATUS "OpenJPEG version ${OPENJPEG_VERSION} found. Only 1.5 and newer support reading of icc profiles.")
-    else()
-      add_definitions("-DHAVE_OPENJPEG_ICC")
-    endif()
-  endif(OPENJPEG_FOUND)
+    list(APPEND SOURCES "common/imageio_j2k.c")
+
+    include_directories(SYSTEM ${OpenJPEG_INCLUDE_DIRS})
+    list(APPEND LIBS ${OpenJPEG_LIBRARIES})
+  endif(OpenJPEG_FOUND)
 endif(USE_OPENJPEG)
 
 #
diff --git a/src/common/imageio_j2k.c b/src/common/imageio_j2k.c
index 84bcd28..7f60e7f 100644
--- a/src/common/imageio_j2k.c
+++ b/src/common/imageio_j2k.c
@@ -36,6 +36,7 @@
 #define JPT_CFMT 2
 
 static char JP2_HEAD[] = { 0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A };
+static char JP2_MAGIC[] = { 0x0d, 0x0a, 0x87, 0x0a };
 static char J2K_HEAD[] = { 0xFF, 0x4F, 0xFF, 0x51, 0x00 };
 // there seems to be no JPIP/JPT magic string, so we can't load it ...
 
@@ -74,7 +75,7 @@ static int get_file_format(const char *filename)
   char *ext = strrchr(filename, '.');
   if(ext == NULL) return -1;
   ext++;
-  if(ext)
+  if(*ext)
   {
     for(i = 0; i < sizeof(format) / sizeof(*format); i++)
     {
@@ -91,100 +92,116 @@ static int get_file_format(const char *filename)
 dt_imageio_retval_t dt_imageio_open_j2k(dt_image_t *img, const char *filename, dt_mipmap_buffer_t *mbuf)
 {
   opj_dparameters_t parameters; /* decompression parameters */
-  opj_event_mgr_t event_mgr;    /* event manager */
   opj_image_t *image = NULL;
   FILE *fsrc = NULL;
-  unsigned char *src = NULL;
-  size_t file_length;
-  opj_dinfo_t *dinfo = NULL; /* handle to a decompressor */
-  opj_cio_t *cio = NULL;
+  unsigned char src_header[12] = { 0 };
+  opj_codec_t *d_codec = NULL;
   OPJ_CODEC_FORMAT codec;
+  opj_stream_t *d_stream = NULL; /* Stream */
   int ret = DT_IMAGEIO_FILE_CORRUPTED;
 
-  int file_format = get_file_format(filename);
-  if(file_format == -1) return DT_IMAGEIO_FILE_CORRUPTED;
+  /* set decoding parameters to default values */
+  opj_set_default_decoder_parameters(&parameters);
+
+  g_strlcpy(parameters.infile, filename, sizeof(parameters.infile));
+
+  parameters.decod_format = get_file_format(filename);
+  if(parameters.decod_format == -1) return DT_IMAGEIO_FILE_CORRUPTED;
 
   if(!img->exif_inited) (void)dt_exif_read(img, filename);
 
-  /* read the input file and put it in memory */
-  /* ---------------------------------------- */
   fsrc = fopen(filename, "rb");
   if(!fsrc)
   {
     fprintf(stderr, "[j2k_open] Error: failed to open `%s' for reading\n", filename);
     return DT_IMAGEIO_FILE_NOT_FOUND;
   }
-  fseek(fsrc, 0, SEEK_END);
-  file_length = ftell(fsrc);
-  fseek(fsrc, 0, SEEK_SET);
-  src = (unsigned char *)malloc(file_length);
-  if(fread(src, 1, file_length, fsrc) != file_length)
+  if(fread(src_header, 1, 12, fsrc) != 12)
   {
-    free(src);
     fclose(fsrc);
     fprintf(stderr, "[j2k_open] Error: fread returned a number of elements different from the expected.\n");
     return DT_IMAGEIO_FILE_NOT_FOUND;
   }
   fclose(fsrc);
 
-  if(memcmp(JP2_HEAD, src, sizeof(JP2_HEAD)) == 0)
+  if(memcmp(JP2_HEAD, src_header, sizeof(JP2_HEAD)) == 0 || memcmp(JP2_MAGIC, src_header, sizeof(JP2_MAGIC)) == 0)
   {
-    file_format = JP2_CFMT; // just in case someone used the wrong extension
+    parameters.decod_format = JP2_CFMT; // just in case someone used the wrong extension
   }
-  else if(memcmp(J2K_HEAD, src, sizeof(J2K_HEAD)) == 0)
+  else if(memcmp(J2K_HEAD, src_header, sizeof(J2K_HEAD)) == 0)
   {
-    file_format = J2K_CFMT; // just in case someone used the wrong extension
+    parameters.decod_format = J2K_CFMT; // just in case someone used the wrong extension
   }
   else // this will also reject jpt files.
   {
-    free(src);
     fprintf(stderr, "[j2k_open] Error: `%s' has unsupported file format.\n", filename);
     return DT_IMAGEIO_FILE_CORRUPTED;
   }
 
-  /* configure the event callbacks (not required) */
-  memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
-  event_mgr.error_handler = error_callback;
-  //   event_mgr.warning_handler = warning_callback;
-  //   event_mgr.info_handler = info_callback;
-
-  /* set decoding parameters to default values */
-  opj_set_default_decoder_parameters(&parameters);
 
   /* decode the code-stream */
   /* ---------------------- */
-  if(file_format == J2K_CFMT) /* JPEG-2000 codestream */
-    codec = CODEC_J2K;
-  else if(file_format == JP2_CFMT) /* JPEG 2000 compressed image data */
-    codec = CODEC_JP2;
-  else if(file_format == JPT_CFMT) /* JPEG 2000, JPIP */
-    codec = CODEC_JPT;
+  if(parameters.decod_format == J2K_CFMT) /* JPEG-2000 codestream */
+    codec = OPJ_CODEC_J2K;
+  else if(parameters.decod_format == JP2_CFMT) /* JPEG 2000 compressed image data */
+    codec = OPJ_CODEC_JP2;
+  else if(parameters.decod_format == JPT_CFMT) /* JPEG 2000, JPIP */
+    codec = OPJ_CODEC_JPT;
   else
   {
-    free(src);
     return DT_IMAGEIO_FILE_CORRUPTED; // can't happen
   }
 
-  /* get a decoder handle */
-  dinfo = opj_create_decompress(codec);
+  d_codec = opj_create_decompress(codec);
+  if(!d_codec)
+  {
+    fprintf(stderr, "[j2k_open] Error: failed to create the decoder\n");
+    return DT_IMAGEIO_FILE_CORRUPTED;
+  }
 
   /* catch events using our callbacks and give a local context */
-  opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
+  opj_set_error_handler(d_codec, error_callback, stderr);
+  // opj_set_warning_handler(d_codec, error_callback, stderr);
+  // opj_set_info_handler(d_codec, error_callback, stderr);
 
   /* setup the decoder decoding parameters using user parameters */
-  opj_setup_decoder(dinfo, &parameters);
+  if(!opj_setup_decoder(d_codec, &parameters))
+  {
+    fprintf(stderr, "[j2k_open] Error: failed to setup the decoder %s\n", parameters.infile);
+    opj_destroy_codec(d_codec);
+    return DT_IMAGEIO_FILE_CORRUPTED;
+  }
 
-  /* open a byte stream */
-  cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
+  d_stream = opj_stream_create_default_file_stream(parameters.infile, 1);
+  if(!d_stream)
+  {
+    fprintf(stderr, "[j2k_open] Error: failed to create the stream from the file %s\n", parameters.infile);
+    opj_destroy_codec(d_codec);
+    return DT_IMAGEIO_FILE_CORRUPTED;
+  }
 
-  /* decode the stream and fill the image structure */
-  image = opj_decode(dinfo, cio);
+  /* Read the main header of the codestream and if necessary the JP2 boxes*/
+  if(!opj_read_header(d_stream, d_codec, &image))
+  {
+    fprintf(stderr, "[j2k_open] Error: failed to read the header\n");
+    opj_stream_destroy(d_stream);
+    opj_destroy_codec(d_codec);
+    opj_image_destroy(image);
+    return EXIT_FAILURE;
+  }
 
-  /* close the byte stream */
-  opj_cio_close(cio);
+  /* Get the decoded image */
+  if(!(opj_decode(d_codec, d_stream, image) && opj_end_decompress(d_codec, d_stream)))
+  {
+    fprintf(stderr, "[j2k_open] Error: failed to decode image!\n");
+    opj_destroy_codec(d_codec);
+    opj_stream_destroy(d_stream);
+    opj_image_destroy(image);
+    return DT_IMAGEIO_FILE_CORRUPTED;
+  }
 
-  /* free the memory containing the code-stream */
-  free(src);
+  /* Close the byte stream */
+  opj_stream_destroy(d_stream);
 
   if(!image)
   {
@@ -193,14 +210,11 @@ dt_imageio_retval_t dt_imageio_open_j2k(dt_image_t *img, const char *filename, d
     goto end_of_the_world;
   }
 
-  if(image->color_space == CLRSPC_SYCC)
+  if(image->color_space == OPJ_CLRSPC_SYCC)
   {
     color_sycc_to_rgb(image);
   }
 
-// FIXME: openjpeg didn't have support for icc profiles before version 1.5
-// this needs some #ifdef magic and proper implementation
-#ifdef HAVE_OPENJPEG_ICC
   if(image->icc_profile_buf)
   {
 #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
@@ -211,7 +225,6 @@ dt_imageio_retval_t dt_imageio_open_j2k(dt_image_t *img, const char *filename, d
     image->icc_profile_buf = NULL;
     image->icc_profile_len = 0;
   }
-#endif
 
   /* create output image */
   /* ------------------- */
@@ -289,7 +302,7 @@ dt_imageio_retval_t dt_imageio_open_j2k(dt_image_t *img, const char *filename, d
 
 end_of_the_world:
   /* free remaining structures */
-  if(dinfo) opj_destroy_decompress(dinfo);
+  opj_destroy_codec(d_codec);
 
   /* free image data structure */
   opj_image_destroy(image);
@@ -299,83 +312,113 @@ end_of_the_world:
 
 int dt_imageio_j2k_read_profile(const char *filename, uint8_t **out)
 {
-#ifdef HAVE_OPENJPEG_ICC
   opj_dparameters_t parameters; /* decompression parameters */
   opj_image_t *image = NULL;
   FILE *fsrc = NULL;
-  unsigned char *src = NULL;
-  size_t file_length;
-  opj_dinfo_t *dinfo = NULL; /* handle to a decompressor */
-  opj_cio_t *cio = NULL;
+  unsigned char src_header[12] = { 0 };
+  opj_codec_t *d_codec = NULL;
   OPJ_CODEC_FORMAT codec;
+  opj_stream_t *d_stream = NULL; /* Stream */
   gboolean res = FALSE;
   unsigned int length = 0;
   *out = NULL;
 
+  /* set decoding parameters to default values */
+  opj_set_default_decoder_parameters(&parameters);
+
+  g_strlcpy(parameters.infile, filename, sizeof(parameters.infile));
+
+  parameters.decod_format = get_file_format(filename);
+  if(parameters.decod_format == -1) return DT_IMAGEIO_FILE_CORRUPTED;
+
   /* read the input file and put it in memory */
   /* ---------------------------------------- */
   fsrc = fopen(filename, "rb");
   if(!fsrc)
   {
-    fprintf(stderr, "[j2k_open] Error: failed to open `%s' for reading\n", filename);
+    fprintf(stderr, "[j2k_read_profile] Error: failed to open `%s' for reading\n", filename);
     goto another_end_of_the_world;
   }
-  fseek(fsrc, 0, SEEK_END);
-  file_length = ftell(fsrc);
-  fseek(fsrc, 0, SEEK_SET);
-  src = (unsigned char *)malloc(file_length);
-  if(fread(src, 1, file_length, fsrc) != file_length)
+  if(fread(src_header, 1, 12, fsrc) != 12)
   {
-    free(src);
     fclose(fsrc);
-    fprintf(stderr, "[j2k_open] Error: fread returned a number of elements different from the expected.\n");
+    fprintf(stderr,
+            "[j2k_read_profile] Error: fread returned a number of elements different from the expected.\n");
     goto another_end_of_the_world;
   }
   fclose(fsrc);
 
-  if(memcmp(JP2_HEAD, src, sizeof(JP2_HEAD)) == 0)
+  if(memcmp(JP2_HEAD, src_header, sizeof(JP2_HEAD)) == 0 || memcmp(JP2_MAGIC, src_header, sizeof(JP2_MAGIC)) == 0)
   {
-    codec = CODEC_JP2;
+    codec = OPJ_CODEC_JP2;
   }
-  else if(memcmp(J2K_HEAD, src, sizeof(J2K_HEAD)) == 0)
+  else if(memcmp(J2K_HEAD, src_header, sizeof(J2K_HEAD)) == 0)
   {
-    codec = CODEC_J2K;
+    codec = OPJ_CODEC_J2K;
   }
   else // this will also reject jpt files.
   {
-    free(src);
-    fprintf(stderr, "[j2k_open] Error: `%s' has unsupported file format.\n", filename);
+    fprintf(stderr, "[j2k_read_profile] Error: `%s' has unsupported file format.\n", filename);
     goto another_end_of_the_world;
   }
 
-  /* set decoding parameters to default values */
-  opj_set_default_decoder_parameters(&parameters);
-  parameters.cp_limit_decoding = LIMIT_TO_MAIN_HEADER;
-
   /* decode the code-stream */
   /* ---------------------- */
 
   /* get a decoder handle */
-  dinfo = opj_create_decompress(codec);
+  d_codec = opj_create_decompress(codec);
+  if(!d_codec)
+  {
+    fprintf(stderr, "[j2k_read_profile] Error: failed to create the decoder\n");
+    return DT_IMAGEIO_FILE_CORRUPTED;
+  }
 
   /* setup the decoder decoding parameters using user parameters */
-  opj_setup_decoder(dinfo, &parameters);
+  opj_setup_decoder(d_codec, &parameters);
+  if(!d_codec)
+  {
+    fprintf(stderr, "[j2k_read_profile] Error: failed to setup the decoder %s\n", parameters.infile);
+    return DT_IMAGEIO_FILE_CORRUPTED;
+  }
 
-  /* open a byte stream */
-  cio = opj_cio_open((opj_common_ptr)dinfo, src, file_length);
+  d_stream = opj_stream_create_default_file_stream(parameters.infile, 1);
+  if(!d_stream)
+  {
+    fprintf(stderr, "[j2k_read_profile] Error: failed to create the stream from the file %s\n", parameters.infile);
+    return DT_IMAGEIO_FILE_CORRUPTED;
+  }
 
-  /* decode the stream and fill the image structure */
-  image = opj_decode(dinfo, cio);
+  /* Read the main header of the codestream and if necessary the JP2 boxes*/
+  if(!opj_read_header(d_stream, d_codec, &image))
+  {
+    fprintf(stderr, "[j2k_read_profile] Error: failed to read the header\n");
+    opj_stream_destroy(d_stream);
+    opj_destroy_codec(d_codec);
+    opj_image_destroy(image);
+    return EXIT_FAILURE;
+  }
 
-  /* close the byte stream */
-  opj_cio_close(cio);
+  /* Get the decoded image */
+  if(!(opj_decode(d_codec, d_stream, image) && opj_end_decompress(d_codec, d_stream)))
+  {
+    fprintf(stderr, "[j2k_read_profile] Error: failed to decode image!\n");
+    opj_destroy_codec(d_codec);
+    opj_stream_destroy(d_stream);
+    opj_image_destroy(image);
+    return DT_IMAGEIO_FILE_CORRUPTED;
+  }
 
-  /* free the memory containing the code-stream */
-  free(src);
+  // FIXME: how to do it without fully-decoding the whole image?
+  // opj_jp2_decode() copies the icc_profile_{buf,len}
+  // from opj_codec_t *d_codec d_codec->color into opj_image_t *image, but
+  // opj_codec_t is private type.
+
+  /* Close the byte stream */
+  opj_stream_destroy(d_stream);
 
   if(!image)
   {
-    fprintf(stderr, "[j2k_open] Error: failed to decode image `%s'\n", filename);
+    fprintf(stderr, "[j2k_read_profile] Error: failed to decode image `%s'\n", filename);
     goto another_end_of_the_world;
   }
 
@@ -391,15 +434,12 @@ int dt_imageio_j2k_read_profile(const char *filename, uint8_t **out)
 
 another_end_of_the_world:
   /* free remaining structures */
-  if(dinfo) opj_destroy_decompress(dinfo);
+  opj_destroy_codec(d_codec);
 
   /* free image data structure */
   opj_image_destroy(image);
 
   return res ? length : 0;
-#else
-  return 0;
-#endif
 }
 
 
@@ -632,7 +672,7 @@ static void color_sycc_to_rgb(opj_image_t *img)
 {
   if(img->numcomps < 3)
   {
-    img->color_space = CLRSPC_GRAY;
+    img->color_space = OPJ_CLRSPC_GRAY;
     return;
   }
 
@@ -658,7 +698,7 @@ static void color_sycc_to_rgb(opj_image_t *img)
     fprintf(stderr, "%s:%d:color_sycc_to_rgb\n\tCAN NOT CONVERT\n", __FILE__, __LINE__);
     return;
   }
-  img->color_space = CLRSPC_SRGB;
+  img->color_space = OPJ_CLRSPC_SRGB;
 } /* color_sycc_to_rgb() */
 
 // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
diff --git a/src/imageio/format/CMakeLists.txt b/src/imageio/format/CMakeLists.txt
index e328cb8..a79f3ee 100644
--- a/src/imageio/format/CMakeLists.txt
+++ b/src/imageio/format/CMakeLists.txt
@@ -22,10 +22,10 @@ if(OPENEXR_FOUND)
 	add_library(exr MODULE "exr.cc")
 endif(OPENEXR_FOUND)
 
-if(OPENJPEG_FOUND)
+if(OpenJPEG_FOUND)
 	list(APPEND MODULES "j2k")
 	add_library(j2k MODULE "j2k.c")
-endif(OPENJPEG_FOUND)
+endif(OpenJPEG_FOUND)
 
 foreach(module ${MODULES})
 	target_link_libraries(${module} ${LIBS})
diff --git a/src/imageio/format/j2k.c b/src/imageio/format/j2k.c
index 0344b75..44a995c 100644
--- a/src/imageio/format/j2k.c
+++ b/src/imageio/format/j2k.c
@@ -63,11 +63,6 @@
 
 #include <openjpeg.h>
 
-#define CINEMA_24_CS 1302083 /*Codestream length for 24fps*/
-#define CINEMA_48_CS 651041  /*Codestream length for 48fps*/
-#define COMP_24_CS 1041666   /*Maximum size per color component for 2K & 4K @ 24fps*/
-#define COMP_48_CS 520833    /*Maximum size per color component for 2K @ 48fps*/
-
 typedef enum
 {
   J2K_CFMT = 0,
@@ -168,14 +163,14 @@ static int initialise_4K_poc(opj_poc_t *POC, int numres)
   POC[0].layno1 = 1;
   POC[0].resno1 = numres - 1;
   POC[0].compno1 = 3;
-  POC[0].prg1 = CPRL;
+  POC[0].prg1 = OPJ_CPRL;
   POC[1].tile = 1;
   POC[1].resno0 = numres - 1;
   POC[1].compno0 = 0;
   POC[1].layno1 = 1;
   POC[1].resno1 = numres;
   POC[1].compno1 = 3;
-  POC[1].prg1 = CPRL;
+  POC[1].prg1 = OPJ_CPRL;
   return 2;
 }
 
@@ -201,7 +196,7 @@ static void cinema_parameters(opj_cparameters_t *parameters)
   parameters->csty |= 0x01;
 
   /*The progression order shall be CPRL*/
-  parameters->prog_order = CPRL;
+  parameters->prog_order = OPJ_CPRL;
 
   /* No ROI */
   parameters->roi_compno = -1;
@@ -220,9 +215,9 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
 
   switch(parameters->cp_cinema)
   {
-    case CINEMA2K_24:
-    case CINEMA2K_48:
-      parameters->cp_rsiz = CINEMA2K;
+    case OPJ_CINEMA2K_24:
+    case OPJ_CINEMA2K_48:
+      parameters->cp_rsiz = OPJ_CINEMA2K;
       if(parameters->numresolution > 6)
       {
         parameters->numresolution = 6;
@@ -233,12 +228,12 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
                 "Image coordinates %d x %d is not 2K compliant.\nJPEG Digital Cinema Profile-3 "
                 "(2K profile) compliance requires that at least one of coordinates match 2048 x 1080\n",
                 image->comps[0].w, image->comps[0].h);
-        parameters->cp_rsiz = STD_RSIZ;
+        parameters->cp_rsiz = OPJ_STD_RSIZ;
       }
       break;
 
-    case CINEMA4K_24:
-      parameters->cp_rsiz = CINEMA4K;
+    case OPJ_CINEMA4K_24:
+      parameters->cp_rsiz = OPJ_CINEMA4K;
       if(parameters->numresolution < 1)
       {
         parameters->numresolution = 1;
@@ -253,7 +248,7 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
                 "Image coordinates %d x %d is not 4K compliant.\nJPEG Digital Cinema Profile-4"
                 "(4K profile) compliance requires that at least one of coordinates match 4096 x 2160\n",
                 image->comps[0].w, image->comps[0].h);
-        parameters->cp_rsiz = STD_RSIZ;
+        parameters->cp_rsiz = OPJ_STD_RSIZ;
       }
       parameters->numpocs = initialise_4K_poc(parameters->POC, parameters->numresolution);
       break;
@@ -263,26 +258,26 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
 
   switch(parameters->cp_cinema)
   {
-    case CINEMA2K_24:
-    case CINEMA4K_24:
+    case OPJ_CINEMA2K_24:
+    case OPJ_CINEMA4K_24:
       for(i = 0; i < parameters->tcp_numlayers; i++)
       {
         if(rates[i] == 0)
         {
           parameters->tcp_rates[0]
               = ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))
-                / (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
+                / (OPJ_CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
         }
         else
         {
           temp_rate
               = ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))
                 / (rates[i] * 8 * image->comps[0].dx * image->comps[0].dy);
-          if(temp_rate > CINEMA_24_CS)
+          if(temp_rate > OPJ_CINEMA_24_CS)
           {
             parameters->tcp_rates[i]
                 = ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))
-                  / (CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
+                  / (OPJ_CINEMA_24_CS * 8 * image->comps[0].dx * image->comps[0].dy);
           }
           else
           {
@@ -290,28 +285,28 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
           }
         }
       }
-      parameters->max_comp_size = COMP_24_CS;
+      parameters->max_comp_size = OPJ_CINEMA_24_COMP;
       break;
 
-    case CINEMA2K_48:
+    case OPJ_CINEMA2K_48:
       for(i = 0; i < parameters->tcp_numlayers; i++)
       {
         if(rates[i] == 0)
         {
           parameters->tcp_rates[0]
               = ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))
-                / (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
+                / (OPJ_CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
         }
         else
         {
           temp_rate
               = ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))
                 / (rates[i] * 8 * image->comps[0].dx * image->comps[0].dy);
-          if(temp_rate > CINEMA_48_CS)
+          if(temp_rate > OPJ_CINEMA_48_CS)
           {
             parameters->tcp_rates[0]
                 = ((float)(image->numcomps * image->comps[0].w * image->comps[0].h * image->comps[0].prec))
-                  / (CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
+                  / (OPJ_CINEMA_48_CS * 8 * image->comps[0].dx * image->comps[0].dy);
           }
           else
           {
@@ -319,7 +314,7 @@ static void cinema_setup_encoder(opj_cparameters_t *parameters, opj_image_t *ima
           }
         }
       }
-      parameters->max_comp_size = COMP_48_CS;
+      parameters->max_comp_size = OPJ_CINEMA_48_COMP;
       break;
     default:
       break;
@@ -334,19 +329,9 @@ int write_image(dt_imageio_module_data_t *j2k_tmp, const char *filename, const v
   dt_imageio_j2k_t *j2k = (dt_imageio_j2k_t *)j2k_tmp;
   opj_cparameters_t parameters; /* compression parameters */
   float *rates = NULL;
-  opj_event_mgr_t event_mgr; /* event manager */
   opj_image_t *image = NULL;
   const int quality = CLAMP(j2k->quality, 1, 100);
 
-  /*
-  configure the event callbacks (not required)
-  setting of each callback is optional
-  */
-  memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
-  event_mgr.error_handler = error_callback;
-  event_mgr.warning_handler = warning_callback;
-  event_mgr.info_handler = info_callback;
-
   /* set encoding parameters to default values */
   opj_set_default_encoder_parameters(&parameters);
 
@@ -357,7 +342,7 @@ int write_image(dt_imageio_module_data_t *j2k_tmp, const char *filename, const v
 
   parameters.tcp_numlayers = 1; /* only one resolution */
   parameters.cp_disto_alloc = 1;
-  parameters.cp_rsiz = STD_RSIZ;
+  parameters.cp_rsiz = OPJ_STD_RSIZ;
 
   parameters.cod_format = j2k->format;
   parameters.cp_cinema = (OPJ_CINEMA_MODE)j2k->preset;
@@ -397,7 +382,7 @@ int write_image(dt_imageio_module_data_t *j2k_tmp, const char *filename, const v
       cmptparm[i].w = w;
       cmptparm[i].h = h;
     }
-    image = opj_image_create(numcomps, &cmptparm[0], CLRSPC_SRGB);
+    image = opj_image_create(numcomps, &cmptparm[0], OPJ_CLRSPC_SRGB);
     if(!image)
     {
       fprintf(stderr, "Error: opj_image_create() failed\n");
@@ -437,6 +422,7 @@ int write_image(dt_imageio_module_data_t *j2k_tmp, const char *filename, const v
         fprintf(stderr, "Error: this shouldn't happen, there is no bit depth of %d for jpeg 2000 images.\n",
                 prec);
         free(rates);
+        opj_image_destroy(image);
         return 1;
     }
   }
@@ -457,58 +443,66 @@ int write_image(dt_imageio_module_data_t *j2k_tmp, const char *filename, const v
   int rc = 1;
   OPJ_CODEC_FORMAT codec;
   if(parameters.cod_format == J2K_CFMT) /* J2K format output */
-    codec = CODEC_J2K;
+    codec = OPJ_CODEC_J2K;
   else
-    codec = CODEC_JP2;
+    codec = OPJ_CODEC_JP2;
 
-  int codestream_length;
-  size_t res;
-  opj_cio_t *cio = NULL;
-  FILE *f = NULL;
+  opj_stream_t *cstream = NULL;
 
   /* get a J2K/JP2 compressor handle */
-  opj_cinfo_t *cinfo = opj_create_compress(codec);
+  opj_codec_t *ccodec = opj_create_compress(codec);
+
+  opj_set_error_handler(ccodec, error_callback, stderr);
+  opj_set_warning_handler(ccodec, warning_callback, stderr);
+  opj_set_info_handler(ccodec, info_callback, stderr);
 
-  /* catch events using our callbacks and give a local context */
-  opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr);
+  g_strlcpy(parameters.outfile, filename, sizeof(parameters.outfile));
 
   /* setup the encoder parameters using the current image and user parameters */
-  opj_setup_encoder(cinfo, &parameters, image);
+  opj_setup_encoder(ccodec, &parameters, image);
 
   /* open a byte stream for writing */
   /* allocate memory for all tiles */
-  cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0);
-
-  /* encode the image */
-  if(!opj_encode(cinfo, cio, image, NULL))
+  cstream = opj_stream_create_default_file_stream(parameters.outfile, OPJ_FALSE);
+  if(!cstream)
   {
-    opj_cio_close(cio);
-    fprintf(stderr, "failed to encode image\n");
+    opj_destroy_codec(ccodec);
+    opj_image_destroy(image);
+    fprintf(stderr, "failed to create output stream\n");
     return 1;
   }
-  codestream_length = cio_tell(cio);
 
-  /* write the buffer to disk */
-  f = fopen(filename, "wb");
-  if(!f)
+  if(!opj_start_compress(ccodec, image, cstream))
   {
-    fprintf(stderr, "failed to open %s for writing\n", filename);
+    opj_stream_destroy(cstream);
+    opj_destroy_codec(ccodec);
+    opj_image_destroy(image);
+    fprintf(stderr, "failed to encode image: opj_start_compress\n");
     return 1;
   }
-  res = fwrite(cio->buffer, 1, codestream_length, f);
-  if(res < (size_t)codestream_length) /* FIXME */
+
+  /* encode the image */
+  if(!opj_encode(ccodec, cstream))
   {
-    fprintf(stderr, "failed to write %d (%s)\n", codestream_length, filename);
-    fclose(f);
+    opj_stream_destroy(cstream);
+    opj_destroy_codec(ccodec);
+    opj_image_destroy(image);
+    fprintf(stderr, "failed to encode image: opj_encode\n");
     return 1;
   }
-  fclose(f);
 
-  /* close and free the byte stream */
-  opj_cio_close(cio);
+  /* encode the image */
+  if(!opj_end_compress(ccodec, cstream))
+  {
+    opj_stream_destroy(cstream);
+    opj_destroy_codec(ccodec);
+    opj_image_destroy(image);
+    fprintf(stderr, "failed to encode image: opj_end_compress\n");
+    return 1;
+  }
 
-  /* free remaining compression structures */
-  opj_destroy_compress(cinfo);
+  opj_stream_destroy(cstream);
+  opj_destroy_codec(ccodec);
 
   /* add exif data blob. seems to not work for j2k files :( */
   if(exif && j2k->format == JP2_CFMT) rc = dt_exif_write_blob(exif, exif_len, filename, 1);
